import { toFixed } from 'az-money-formatter'

const styleMap = ['percent', 'ops', 'all']

const resultHandlersOfStyles = {
  percent: styleHandlerOfPercent,
  ops: styleHandlerOfOps,
}

export function handleResult(results, style, frequency) {
  const resultsFiltered = []

  for (let result of results) {
    const resultFiltered = filterResult(filterResult(result, 0.1), 0.03)
    if (!resultFiltered.length) return
    resultsFiltered.push(resultFiltered)
  }

  if (!styleMap.includes(style)) style = 'percent'

  return resultHandlersOfStyles[style](resultsFiltered, frequency)
}

function filterResult(result, threshold) {
  const average = averageResult(result)
  if (!average) throw new Error('az-benchmark: Frequency is too small.')
  return average * threshold >= 1
    ? result.filter((res) => res >= (1 - threshold) * average && res <= (1 + threshold) * average)
    : result
}

function styleHandlerOfPercent(results) {
  const averages = results.map((result) => averageResult(result))
  const min = Math.min(...averages)

  return averages.map((average) =>
    (+toFixed(average / min, 4)).toLocaleString('zh', { style: 'percent', minimumFractionDigits: 2 })
  )
}
function styleHandlerOfOps(results, frequency) {
  return results.map((result) => {
    const maxOps = (frequency / Math.min(...result)) * 1000
    const minOps = (frequency / Math.max(...result)) * 1000

    const averageOps = (frequency / averageResult(result)) * 1000
    const fluctuation = Math.max((maxOps - averageOps) / averageOps, (averageOps - minOps) / averageOps)
    return (
      toFixed(averageOps) +
      ' ops/sec ±' +
      (+toFixed(fluctuation, 4)).toLocaleString('zh', { style: 'percent', minimumFractionDigits: 2 })
    )
  })
}

function averageResult(result) {
  return result.reduce((res, item) => res + item, 0) / result.length
}
